﻿#include "pch.h"
#if _QG_ENABLE_WIDGET
#include "qgp/qgach.h"
#include "qgp/qgaud.h"
#include "qgp/qguwgs.h"

//////////////////////////////////////////////////////////////////////////
// 라벨
KIMPL_SUBCLASS(qwScroll, "WidgetScroll");

qwScroll::qwScroll(qgWidgetType type)
	: super_type(type)
	, _pos(0)
	, _pagesize(1)
	, _count(10)
	, _thumb(true)
	, _indicator(IndNone)
{
	_insts.input = true;
	_insts.fill = true;
}

//
void qwScroll::OnInitialize()
{
	super_type::OnInitialize();

	_rinds[IndUp] = _shed->GetResource(QGWELM_SCROLL_IND_UP);
	_rinds[IndDown] = _shed->GetResource(QGWELM_SCROLL_IND_DOWN);
	_rinds[IndThumb] = _shed->GetResource(QGWELM_SCROLL_IND_THUMB);
	_rinds[IndTrack] = _shed->GetResource(QGWELM_SCROLL_IND_TRACK);
}

bool qwScroll::OnUpdate(float adv)
{
	BuildBound();

	if (NeedRefresh())
	{
		kint w = _client.Width();

		// 위-아래는 높낮이를 같게 하기 위해 높이=너비로 함
		_binds[IndUp].Set(_client.left, _client.top, _client.right, _client.top + w);
		_binds[IndDown].Set(_client.left, _client.bottom - w, _client.right, _client.bottom);
		_binds[IndTrack].Set(_client.left, _binds[IndUp].bottom, _client.right, _binds[IndDown].top);
		_binds[IndThumb].left = _client.left;
		_binds[IndThumb].right = _client.right;

		// 손톱도 리플레시
		_thumb_refresh = true;

		ResetRefresh();
	}

	// 누르고 있나
	if (_indicator != IndNone)
	{
		_ind_adv += adv;

		if (_binds[IndUp].OnPoint(_save_pt.x, _save_pt.y))
		{
			switch ((ksize_t)_indicator)
			{
				case qwScroll::IndUp:
					if (_ind_adv > 0.3f)
					{
						Scroll(-1);
						_indicator = IndRepUp;
						_ind_adv = 0.0f;
					}
					break;

				case qwScroll::IndRepUp:
					if (_ind_adv > 0.05f)
					{
						Scroll(-1);
						_ind_adv = 0.0f;
					}
					break;
			}
		}
		else if (_binds[IndDown].OnPoint(_save_pt.x, _save_pt.y))
		{
			switch ((ksize_t)_indicator)
			{
				case qwScroll::IndDown:
					if (_ind_adv > 0.3f)
					{
						Scroll(1);
						_indicator = IndRepDown;
						_ind_adv = 0.0f;
					}
					break;

				case qwScroll::IndRepDown:
					if (_ind_adv > 0.05f)
					{
						Scroll(1);
						_ind_adv = 0.0f;
					}
					break;
			}
		}
	}

	// 손톱 위치 업뎃
	if (_thumb_refresh)
	{
		kint len = _count;

		if (len > _pagesize)
		{
			// 페이지보타 크면 그려야...
			kint rh = _binds[IndTrack].Height();
			kint ht = K_MAX(rh*_pagesize / len, 8);
			kint mp = len - _pagesize;

			_binds[IndThumb].top = _binds[IndTrack].top + (_pos - 0) * (rh - ht) / mp;	// 0=min
			_binds[IndThumb].bottom = _binds[IndThumb].top + ht;
			_thumb = true;
		}
		else
		{
			// 페이지보다 작으면 안그림
			_thumb = false;
		}

		_thumb_refresh = false;
	}

	return true;
}

void qwScroll::OnDraw()
{
	// 트랙 배경, 채움 여부 설정으로 그리기 조정 가능
	if (CanFill())
		_shed->DrawFillRect(_binds[IndTrack], _rinds[IndTrack], _tex);

	//
	int n = _binds[IndUp].Width();
	//int m = _ibound[IndUp].Height();

	if (n > 0)
	{
		// 업
		_shed->DrawFillRect(_binds[IndUp], _rinds[IndUp], _tex);

		// 다운
		_shed->DrawFillRect(_binds[IndDown], _rinds[IndDown], _tex);

		// 손톱
		if (_thumb)
			_shed->DrawFillRect(_binds[IndThumb], _rinds[IndThumb], _tex);
	}

	// 외곽선
	if (HasBorder())
		_shed->DrawEmptyRect(_client, _color_border);

	qwCtrl::OnDraw();
}

//
const qbWidgetResource& qwScroll::GetResource(qgWidgetElement nth)
{
	if (nth >= QGWELM_SCROLL_IND_UP && nth <= QGWELM_SCROLL_IND_TRACK)
		return _rinds[nth - QGWELM_SCROLL_IND_UP];

	return super_type::GetResource(nth);
}

//
void qwScroll::SetPosition(kint pos, bool initvalue)
{
	if (pos < 0)
		pos = 0;
	else if (pos >= _count)
		pos = _count - 1;

	if (_pos > pos)
		_pos = pos;
	else if ((_pos + _pagesize) <= pos)
		_pos = pos - _pagesize + 1;

	ValidateRange();

	_thumb_refresh = true;
}

//
void qwScroll::SetPosition(qgWidgetPlace place)
{
	switch (place)
	{
		case QGWPLACE_LEFT:
			SetPosition(0);
			break;

		case QGWPLACE_RIGHT:
			SetPosition(_count - 1);
			break;

		case QGWPLACE_CENTER:
			SetPosition(_count / 2);
			break;
	}

	SetRefresh();
}

//
void qwScroll::SetPageSize(kint size)
{
	_pagesize = size;

	ValidateRange();

	_thumb_refresh = true;
}

//
void qwScroll::SetCount(kint count)
{
	_count = count;

	ValidateRange();

	_thumb_refresh = true;
}

//
bool qwScroll::SetResource(qgWidgetElement nth, const qbWidgetResource& res)
{
	if (nth >= QGWELM_SCROLL_IND_UP && nth <= QGWELM_SCROLL_IND_TRACK)
	{
		_rinds[nth - QGWELM_SCROLL_IND_UP] = res;
		return true;
	}

	return super_type::SetResource(nth, res);
}

//
void qwScroll::Scroll(int delta)
{
	_pos += delta;

	ValidateRange();
	_thumb_refresh = true;

	if (_ecb_position_changed)
		_ecb_position_changed(this, _pos);
}

//
void qwScroll::ValidateRange()
{
	if (_pos < 0 || _count <= _pagesize)
		_pos = 0;
	else if ((_pos + _pagesize) >= _count)
		_pos = _count - _pagesize;
}

//
bool qwScroll::OnMouseMove(kint x, kint y, const tpl::Point& relative, kushort state)
{
	_save_pt.Set(x, y);

	if (_drag)
	{
		kint dy = y - _save_scrl;
		_binds[IndThumb].bottom += dy - _binds[IndThumb].top;
		_binds[IndThumb].top = dy;

		if (_binds[IndThumb].top < _binds[IndTrack].top)
			_binds[IndThumb] = _binds[IndThumb].Offset(0, _binds[IndTrack].top - _binds[IndThumb].top);
		else if (_binds[IndThumb].bottom>_binds[IndTrack].bottom)
			_binds[IndThumb] = _binds[IndThumb].Offset(0, _binds[IndTrack].bottom - _binds[IndThumb].bottom);

		kint fst = _count - _pagesize;
		kint mth = _binds[IndTrack].Height() - _binds[IndThumb].Height();

		_pos = 0 + (_binds[IndThumb].top - _binds[IndTrack].top + mth / (fst * 2)) * fst / mth;

		if (_ecb_position_changed)
			_ecb_position_changed(this, _pos);

		return false;
	}

	return true;
}

//
bool qwScroll::OnMouseDown(kint x, kint y, kushort button)
{
	_save_pt.Set(x, y);

	if (button == QIM_LEFT)
	{
		if (_binds[IndUp].OnPoint(x, y))
		{
			Scroll(-1);

			_indicator = IndUp;
			_ind_adv = 0.0f;

			return false;
		}

		if (_binds[IndDown].OnPoint(x, y))
		{
			Scroll(1);

			_indicator = IndDown;
			_ind_adv = 0.0f;

			return false;
		}

		if (_binds[IndThumb].OnPoint(x, y))
		{
			_drag = true;
			_save_scrl = y - _binds[IndThumb].top;

			return false;
		}

		if (x > _client.left && x < _client.right)
		{
			if (y < _binds[IndThumb].top && y > _binds[IndTrack].top)
			{
				Scroll(-_pagesize);

				return false;
			}
			else if (y > _binds[IndThumb].bottom && y < _binds[IndTrack].bottom)
			{
				Scroll(+_pagesize);

				return false;
			}
		}
	}

	return true;
}

//
bool qwScroll::OnMouseUp(kint x, kint y, kushort button)
{
	if (button == QIM_LEFT)
	{
		_drag = false;
		_indicator = IndNone;
		_thumb_refresh = true;
	}

	return true;
}

#endif	// _QG_ENABLE_WIDGET
